package com.chisheng.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:jdbc.properties")
@ComponentScan({"com.chisheng.service", "com.chisheng.mapper"})
@SuppressWarnings("all")  /* Application context not configured for this file */
public class CustomConfiguration implements EnvironmentAware {

    /* 声明式事务的使用步骤
     * 1) 通过 @EnableTransactionManagement 注解开启声明式事务
     * 2) 配置 PlatformTransactionManger 管理 dataSource 的事务
     * 3) 在需要事务控制的方法加上 @Transacional 注解 */

    /* 执行流程
     * 导入 TransactionManagementConfigurationSelector > ImportSelector
     *  导入了 AutoProxyRegistrar，ProxyTransactionManagementConfiguration
     *
     * AutoProxyRegistrar > ImportBeanDefinitionRegistrar
     *  AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
     *  registerAutoProxyCreatorIfNecessary(registry, null);
     *  registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
     *
     * InfrastructureAdvisorAutoProxyCreator > SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
     *
     * ProxyTransactionManagementConfiguration | @Configuration
     *  BeanFactoryTransactionAttributeSourceAdvisor
     *
     *  TransactionAttributeSource (包含事务 @Transactional 注解上的信息)
     *    子实现 AnnotationTransactionAttributeSource
     *      this.annotationParsers.add(new SpringTransactionAnnotationParser());
     *        this.annotationParsers.add(new SpringTransactionAnnotationParser());
     *  TransactionInterceptor > MethodInterceptor
     *
     */

    private Environment environment;

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(environment.getProperty("jdbc.driver"));
        dataSource.setUrl(environment.getProperty("jdbc.url"));
        dataSource.setUsername(environment.getProperty("jdbc.user"));
        dataSource.setPassword(environment.getProperty("jdbc.password"));
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }

    @Bean
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

}
